/*
 * @(#)FreemarkerResultTestCase.java $version 2010. 8. 11
 *
 * Copyright 2007-2010 NHN Corp. All rights Reserved. 
 * NHN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */
package com.nhncorp.usf.core.result.helper;

import com.nhncorp.lucy.common.config.model.ApplicationInfo;
import com.nhncorp.lucy.common.util.LocaleUtil;
import com.nhncorp.lucy.web.helper.ServletHelper;
import com.nhncorp.usf.core.UsfConfiguration;
import com.nhncorp.usf.core.config.runtime.ResultPageInfo;
import com.nhncorp.usf.core.config.runtime.ResultPageInfo.DISPATCHER_TYPE;
import com.nhncorp.usf.core.result.template.AbstractTemplateResult;
import com.nhncorp.usf.core.result.template.FreemarkerResult;
import com.nhncorp.usf.core.result.template.NotExistTemplateException;
import com.nhncorp.usf.core.result.template.TemplateProcessException;
import com.nhncorp.usf.core.servlet.ServletContextHolder;
import com.nhncorp.usf.core.util.ScriptUtil;
import com.opensymphony.xwork.ActionContext;
import freemarker.template.Configuration;
import junit.framework.Assert;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;

/**
 * {@link FreemarkerResult} TestCase.
 *
 * @author Web Platform Development Team
 */
public class FreemarkerResultTestCase {
    Configuration configuration;
    AbstractTemplateResult templateResult;
    ResultPageInfo resultPageInfo;
    static javax.script.ScriptEngineManager scriptEngineManager = new javax.script.ScriptEngineManager();
    private Log log = LogFactory.getLog(FreemarkerResultTestCase.class);

    @BeforeClass
    public static void beforeInit() throws FreemarkerInitializeException {
        MockServletContext mockServletContext = new MockServletContext() {
            @Override
            public String getRealPath(String path) {
                return super.getRealPath("/WEB-INF/templates" + path);
            }
        };
        UsfConfiguration usfConfiguration = new UsfConfiguration("/WEB-INF/templates", "nhn");
        UsfConfigurationHolder.setUsfConfiguration(usfConfiguration);
        Locale locale = new Locale("ko", "KR");
        ApplicationInfo.setLocale(locale);
        LocaleUtil.setUserLocale(locale);
        ServletContextHolder.set(mockServletContext);
    }

    @AfterClass
    public static void afterInit() throws FreemarkerInitializeException {
        ServletContextHolder.set(new MockServletContext());
    }

    @Before
    public void initialize() throws Exception {
        MockHttpServletRequest request = new MockHttpServletRequest();
        MockHttpServletResponse response = new MockHttpServletResponse();
        ActionContext.getContext().put(ServletHelper.HTTP_REQUEST, request);
        ActionContext.getContext().put(ServletHelper.HTTP_RESPONSE, response);
        ServletContextHolder.set(new MockServletContext());
        ApplicationInfo.setFileEncoding("utf-8");
        FreemarkerConfigFactory.resetConfiguration();
        FreemarkerConfigFactory.setTemplateLoader(null);
        templateResult = new FreemarkerResult();

        String scriptDirPath = ServletContextHolder.get().getRealPath("/scripts");
        ServletContextHolder.setContextRealPath(scriptDirPath);
        ScriptUtil.loadJSFile(scriptDirPath);
    }

    @Test
    public void executeNoTemplateFile() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "hello ${name}.");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            templateResult.execute(resultPageInfo, parameterMap);

            String expectedContent = "hello Gildong,Hong.";
            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch (Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void executeTemplateFile() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/WEB-INF/templates/email.ftl");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            templateResult.execute(resultPageInfo, parameterMap);

            String expectedContent = "안녕하세요. Gildong,Hong 님. 이 메일은 테스트 메일입니다. 감사합니다.";
            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch (Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void executeTemplateDirectiveMethod1() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/WEB-INF/templates/greeting.ftl");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            templateResult.execute(resultPageInfo, parameterMap);

            log.debug(" executeTemplateDirectiveMethod1 expectedContent : " + response.getContentAsString().trim());
            String expectedContent = "Hello. Gildong,Hong!  0MyNameischoco My favorite fruit :   1. apple 2. banana   1. choco 2. cocoa";
            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch (Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void executeTemplateDirectiveMethod2() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/WEB-INF/templates/hello.ftl");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("alpha", "one");
            parameterMap.put("beta", "two");
            parameterMap.put("gamma", "three");
            templateResult.execute(resultPageInfo, parameterMap);

            log.debug(" executeTemplateDirectiveMethod2 expectedContent : " + response.getContentAsString().trim());
            String expectedContent = "replace string value (with javascript) :  onetwothree / replace string value (with groovy) :  threeonetwo";
            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch (Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    public void executeTemplateDirectiveMethod3() throws Exception {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/WEB-INF/templates/example.ftl");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "choco");
            templateResult.execute(resultPageInfo, parameterMap);

            log.debug(" executeTemplateDirectiveMethod3 expectedContent : " + response.getContentAsString().trim());
            String expectedContent = "Hello, choco!   My name is choco.  Goodbye, nhncorp!   See you again [choco].";
            Assert.assertEquals(expectedContent, response.getContentAsString().trim());
        } catch (Exception except) {
            except.printStackTrace();
            Assert.fail();
        }
    }

    /**
     * TemplateProcessExcetion test.
     */
    @Test
    public void testTemplateProcessException() throws InvocationTargetException, IllegalAccessException {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/WEB-INF/templates/email.ftl");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        @SuppressWarnings("unused")
		MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            templateResult.execute(resultPageInfo, parameterMap);
        } catch (TemplateProcessException except) {
            except.printStackTrace();
            Assert.assertEquals("freemarker.core.InvalidReferenceException: Expression name is undefined on line 1, column 10 in WEB-INF/templates/email.ftl.", except.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }

    @Test
    @SuppressWarnings("unused")
    public void testNotExistTemplateException() throws InvocationTargetException, IllegalAccessException {
        resultPageInfo = new ResultPageInfo(DISPATCHER_TYPE.redirect, "/WEB-INF/templates/mail.ftl");
        resultPageInfo.setId("dummy_id");
        resultPageInfo.getProperties().setProperty("contentType", "text/html");
        resultPageInfo.getProperties().setProperty("language", "freemarker");
        resultPageInfo.getProperties().setProperty("encoding", "utf-8");

        BeanUtils.populate(templateResult, resultPageInfo.getProperties());

        		MockHttpServletResponse response = ((MockHttpServletResponse) ServletHelper.getResponse());
        try {
            Map<String, Object> parameterMap = new HashMap<String, Object>();
            parameterMap.put("name", "Gildong,Hong");
            templateResult.execute(resultPageInfo, parameterMap);
        } catch (NotExistTemplateException except) {
            except.printStackTrace();
            Assert.assertEquals("can't create template (/WEB-INF/templates/mail.ftl)", except.getMessage());
        } catch (Exception e) {
            e.printStackTrace();
            Assert.fail();
        }
    }
}
